﻿using System;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;

namespace Coding4Fun.Maelstrom.Communication
{
	public sealed class SocketListener
	{
		public IGamePacket LastPacket { get; private set; }
		public bool Connected { get; private set; }

		private readonly StreamSocketListener _listener;
		private DataReader _reader;
		private DataWriter _writer;

		public SocketListener()
		{
			_listener = new StreamSocketListener();
			_listener.ConnectionReceived += OnConnectionReceived;
		}

		public async void Listen(int port)
		{
			await _listener.BindServiceNameAsync(port.ToString());
		}

		private void OnConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
		{
			_reader = new DataReader(args.Socket.InputStream);
			_writer = new DataWriter(args.Socket.OutputStream);

			Connected = true;

			Task.Run(async () =>
			{
				while(true)
				{
					await _reader.LoadAsync(sizeof(Int32));
					PacketType type = (PacketType)_reader.ReadInt32();
					LastPacket = await ReadPacketAsync(type);
				}
			});
		}

		private async Task<IGamePacket> ReadPacketAsync(PacketType type)
		{
			switch(type)
			{
				case PacketType.UserInputPacket:
					UserInputPacket uip = new UserInputPacket();
					await uip.FromDataReaderAsync(_reader);
					return uip;

				case PacketType.GameStatePacket:
					GameStatePacket gsp = new GameStatePacket();
					await gsp.FromDataReaderAsync(_reader);
					return gsp;

				default:
					throw new Exception("Unknown packet type received: " + type);
			}
		}

		public IAsyncAction WritePacketAsync(IGamePacket packet)
		{
			return WritePacketAsyncInternal(packet).AsAsyncAction();
		}

		private async Task WritePacketAsyncInternal(IGamePacket packet)
		{
			if(_writer != null)
			{
				_writer.WriteInt32((int) packet.Type);
				packet.WritePacket(_writer);
				await _writer.StoreAsync();
			}
		}
	}
}
